Passed
Push — master ( d62fdb...68d35d )
by Plamen
01:36
created

table.js ➔ initInstance   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 27
Bugs 0 Features 2
Metric Value
cc 1
eloc 28
c 27
b 0
f 2
nc 1
nop 0
dl 0
loc 39
rs 9.208
1
var TableHelper = {
2
    BuildRequest: {
3
        Sort: function (rq, strDesc){
4
            function sortBySpan(span, i){
5
                var order = span.innerHTML;
6
                if(order.length === 1){
7
                    rq.colNo = i;
8
                    rq.colOrd = order === strDesc ? "desc" : "asc";
9
                }
10
                return rq.colNo === i;
11
            }
12
13
            var thTags = document.getElementById(rq.tableId)
14
                    .getElementsByTagName("thead")[0]
15
                    .getElementsByTagName("th");
16
            var length = thTags.length;
17
            for(var i = 0; i < length; i++){
18
                var link = thTags[i].getElementsByTagName("a")[0];
19
                if(link){
20
                    var span = link.getElementsByTagName("span")[0];
21
                    if(span && sortBySpan(span, i)){
22
                        break;
23
                    }
24
                }
25
            }
26
        },
27
        Filter: function (rq){
28
            function getFilterFieldsByTableID(tableID){
29
                var fields = {filterBy: null, filter: null};
30
                var filterDiv = getFilterDivByTableIDOrNull(tableID);
31
                if(filterDiv !== null){
32
                    setFilterBy(fields, filterDiv);
33
                    setFilterValue(fields, filterDiv);
34
                }
35
                return fields;
36
            }
37
            function getFilterDivByTableIDOrNull(tableID){
38
                var res = null;
39
                if(document.getElementById(tableID).parentNode.getElementsByTagName("div").length > 0){
40
                    for(var i = 0; i < document.getElementById(tableID).parentNode.getElementsByTagName("div").length; i++){
41
                        if(document.getElementById(tableID).parentNode.getElementsByTagName("div")[i].getAttribute("class") === "filter"){
42
                            return document.getElementById(tableID).parentNode.getElementsByTagName("div")[i];
43
                        }
44
                    }
45
46
                }
47
                return res;
48
            }
49
            function setFilterBy(fields, filterDiv){
50
                var slctObj = filterDiv.getElementsByTagName("select")[0];
51
                if(slctObj && slctObj.options[slctObj.selectedIndex].value !== "all"){
52
                    fields.filterBy = slctObj.options[slctObj.selectedIndex].value;
53
                }
54
            }
55
            function setFilterValue(fields, filterDiv){
56
                var textObj = filterDiv.getElementsByTagName("input")[0];
57
                if(textObj && textObj.value && textObj.value.length !== 0){
58
                    fields.filter = encodeURIComponent(textObj.value.trim());
59
                }
60
            }
61
62
            var r = getFilterFieldsByTableID(rq.tableId);
63
            if(r.filter !== null){
64
                rq.filter = r.filter;
65
            }
66
            if(r.filterBy !== null){
67
                rq.filterBy = r.filterBy;
68
            }
69
        },
70
        Run: (function(rq, crntTableId, strDesc){
71
            rq.tableId = crntTableId;
72
            TableHelper.BuildRequest.Sort(rq, strDesc);
73
            TableHelper.BuildRequest.Filter(rq);
74
        })
75
    },
76
    ColumnHover: function(tableContainer, index){
77
        var rows = document.getElementById(tableContainer).rows;
78
        var upto = rows.length - 1;
79
        if(typeof index === "undefined"){
80
            ColumnHoverRelease(rows, upto);
81
        } else {
82
            for(var i = 0; i < upto; i++){
83
                rows[i].cells[index].setAttribute("lang", "col-hover");
84
            }
85
        }
86
        function ColumnHoverRelease(rows, upto){
87
            for(var i = 0; i < upto; i++){
88
                for(var j = 0; j < rows[i].cells.length; j++){
89
                    if(rows[i].cells[j].lang){
90
                        rows[i].cells[j].removeAttribute("lang");
91
                    }
92
                }
93
            }
94
        };
95
    },
96
    Draw: {
97
        Section: function(tableContainer, dt, tSection){
98
            var section = tSection === "tfoot" ? "tfoot" : "tbody";
99
            var tSec = document.getElementById(tableContainer)
100
                        .getElementsByTagName(section)[0];
101
            Clear(tSec, TableHelper.IePrior(9));
102
            for(var i = 0; i < dt.length; i++){
103
                var row = dt[i];
104
                var tRow = document.createElement("tr");
105
                Row(row, tRow);
106
                tSec.appendChild(tRow);
107
                if(section === "tfoot"){
108
                    TableHelper.ProcessPaginationLinks(tSec);
109
                }
110
            }
111
            function Clear(tSection, iePrior9){
112
                if(iePrior9){
113
                    if(tSection.firstChild){
114
                        while(tSection.firstChild){
115
                            tSection.removeChild(tSection.firstChild);
116
                        }
117
                    }
118
                }else{
119
                    tSection.innerHTML = "";
120
                }
121
            }
122
            function Row(row, tRow){
123
                for(var cell in row){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
124
                    var tCell = document.createElement("td");
125
                    if(typeof row[cell] === "string" || 
126
                       typeof row[cell] === "number"
127
                    ){
128
                        tCell.innerHTML = row[cell];
129
                    }else if(typeof row[cell] === "object"){
130
                        RowCellFromObject(row, cell, tCell);
131
                    }
132
                    tRow.appendChild(tCell);
133
                }
134
            }
135
            function RowCellFromObject(row, cell, tCell){
136
                for(var attr in row[cell]){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
137
                    if(typeof row[cell][attr] === "string"){
138
                        tCell.innerHTML = row[cell][attr];
139
                    }else if(typeof row[cell][attr] === "object"){
140
                        for(var v in row[cell][attr]){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
141
                            tCell.setAttribute(v, row[cell][attr][v]);
142
                        }
143
                    }
144
                }
145
            }
146
        },
147
        Run: function(tableContainer, d, instance){
148
            this.Section(tableContainer, d.body);
149
            this.Section(tableContainer, d.footer, "tfoot");
150
            if(instance.rq !== null){
151
                var hover = document.getElementById(instance.rq.tableId)
152
                            .getElementsByTagName("th")[instance.rq.colNo].lang;
153
                if(hover){
154
                    instance.ColumnHover(tableContainer, instance.rq.colNo);
155
                }
156
            }
157
        }
158
    },
159
    Export: function(lnk, eType, strDesc){
160
        var request = {};
161
        var crntTableId = TableHelper.GetParent(lnk, "table").getAttribute("id");
162
        TableHelper.BuildRequest.Run(request, crntTableId, strDesc);
163
        request.exportType = ["CSV", "Excel"].indexOf(eType) >= 0 ?
164
                                        eType : 
165
                                        "csv";
166
        window.open(TableHelper.RequestToUrl(request));
167
        return false;
168
    },
169
    Filter: {
170
        Run: function(field, instance, rq, strDesc){
171
            var crntTableId = TableHelper.Filter.GetTableId(field);
172
            if(crntTableId !== null){
173
                var request = {};
174
                var exRq = rq;
175
                TableHelper.BuildRequest.Run(request, crntTableId, strDesc);
176
                if(exRq === null ||
177
                    request.filter !== exRq.filter ||
178
                    request.filterBy !== exRq.filterBy
179
                ){
180
                    TableHelper.LoadData.Run(crntTableId, request, instance);
181
                }
182
            }
183
        },
184
        GetTableId: function(field){
185
            if(field.tagName.toLowerCase() !== "select"){
186
                return field.getAttribute("data-table-id");
187
            }
188
            var f = field.parentNode.parentNode.getElementsByTagName("input")[0];
189
            return '' === f.value ? null : f.getAttribute("data-table-id");
190
        }
191
    },
192
    Init: {
193
        Run: function(tableId){
194
            var tContainer = document.getElementById(tableId);
195
            if(!TableHelper.IePrior(9)){
196
                TableHelper.Init.SetColumnsHoverEffect(tContainer, tableId);
197
            }
198
            var tfoot = tContainer.getElementsByTagName("tfoot")[0];
199
            TableHelper.ProcessPaginationLinks(tfoot);
200
        },
201
        SetColumnsHoverEffect: function (tContainer, tableId){
202
            var tHcells = tContainer.rows[0].cells;
203
            for(var i = 0; i < tHcells.length; i++){
204
                if(tHcells[i].firstChild.tagName === "A"){
205
                    tHcells[i].firstChild.setAttribute("onmouseover", "table.ColumnHover('" + tableId + "'," + i + ");");
206
                    tHcells[i].firstChild.setAttribute("onmouseout", "table.ColumnHover('" + tableId + "');");
207
                }
208
            }
209
        }
210
    },
211
    GoPage: {
212
        Run: function(lnk, instance, strDesc){
213
            var request = {};
214
            var crntTableId = TableHelper.GetParent(lnk, "table").getAttribute("id");
215
            TableHelper.BuildRequest.Run(request, crntTableId, strDesc);
216
            request.pageNo = TableHelper.GoPage.GetNo(lnk, crntTableId);
217
            TableHelper.LoadData.Run(crntTableId, request, instance);
218
            return false;  
219
        },
220
        GetNo: function(lnk, tableId){
221
            //check & serve pagination jump links
222
            var jumpDir = lnk.innerHTML.trim().substr(0, 1);
223
            if(jumpDir === "+" || jumpDir === "-"){
224
                var current = document.getElementById(tableId)
225
                                .querySelector("tfoot .paging .a").innerHTML;
226
                var jump = lnk.innerHTML.replace("K", "000").replace("M", "000000000");
227
                var jumpPage = (parseInt(current) + parseInt(jump));
228
                lnk.parentNode.setAttribute("data-page", jumpPage);
229
                lnk.style.transform = "none";
230
            }
231
            return lnk.parentNode.hasAttribute("data-page") ?
232
                    lnk.parentNode.getAttribute("data-page") :
233
                    lnk.innerHTML;
234
        }
235
    },
236
    LoadData: {
237
        tail: null,
238
        Run: function(tableContainer, rq, instance){
239
            var tail = TableHelper.LoadData.tail;
240
            if(tail!==null){ tail.abort();}
241
            TableHelper.LoadData.SetVisability(tableContainer, false);
242
            var xmlhttp = window.XMLHttpRequest ? 
243
                            new XMLHttpRequest() : //IE7+, Firefox, Chrome, Opera, Safari
244
                            new window.ActiveXObject("Microsoft.XMLHTTP");//IE6, IE5
245
            xmlhttp.onreadystatechange = function(){
246
                if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
247
                    var d = JSON.parse(xmlhttp.responseText);
248
                    TableHelper.Draw.Run(tableContainer, d, instance);
249
                    TableHelper.LoadData.SetVisability(tableContainer, true);
250
                    instance.LoadEndCalback(tableContainer);
251
                }
252
            };
253
            xmlhttp.open("GET", TableHelper.RequestToUrl(rq), true);
254
            xmlhttp.send();
255
            TableHelper.LoadData.tail = xmlhttp; //put at tail to can abort later previous request
256
        },
257
        SetVisability: function(tableContainer, flag){
258
            var tbl = document.getElementById(tableContainer);
259
            if(flag === true){
260
                tbl.style.filter = "none";
261
                tbl.style.opacity = "1";
262
                tbl.style.cursor = "auto";
263
            }else if(flag === false){
264
                tbl.style.filter = "blur(1px)";
265
                tbl.style.opacity = "0.8";
266
                tbl.style.cursor = "wait";
267
            }else{
268
                console.error("table error in the flag value");
269
            }
270
        }
271
    },
272
    Sort: function(colNo, lnk, instance, strDesc, strAsc){
273
        var request = {};
274
        var crntTableId = TableHelper.GetParent(lnk, "table").getAttribute("id");
275
        TableHelper.BuildRequest.Run(request, crntTableId, strDesc);
276
        if(Math.round(colNo) === request.colNo){
277
            request.colOrd = (request.colOrd === "asc" ? "desc" : "asc");
278
        }else{
279
            request.colNo = Math.round(colNo);
280
            request.colOrd = "asc";
281
        }
282
        TableHelper.LoadData.Run(crntTableId, request, instance);
283
        /* Clear and add new sort arrow */
284
        var headSpans = TableHelper.GetParent(lnk, "thead").getElementsByTagName("span");
285
        var length = headSpans.length;
286
        for(var i = 0; i < length; i++){
287
            headSpans[i].innerHTML = "";
288
        }
289
        lnk.getElementsByTagName("span")[0].innerHTML = (request.colOrd === "desc" ? strDesc : strAsc);
290
    },
291
292
    IePrior: function(v){
293
        var rv = false;
294
        if(window.navigator.appName === 'Microsoft Internet Explorer'){
295
            var ua = window.navigator.userAgent;
296
            var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
297
            if(re.exec(ua) !== null){
298
                rv = parseFloat(RegExp.$1);
299
            }
300
            rv = rv < v ? true : false;
301
        }
302
        return rv;
303
    },
304
    GetParent: function(obj, objType){
305
        while(obj && obj.tagName !== objType.toUpperCase()){
306
            obj = obj.parentNode;
307
        }
308
        return obj;
309
    },
310
    ProcessPaginationLinks: function(tfoot){
311
        var pLinks = tfoot.querySelectorAll(".paging a");
312
        if(pLinks.length > 0){
313
            for(var j = 0; j < pLinks.length; j++){
314
                pLinks[j].setAttribute("href", "javascript:void(0);");
315
                pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
316
            }
317
        }
318
    },
319
    RequestToUrl: function(rq){
320
        var url = location.pathname + ".json" + location.search;
321
        if(typeof rq === "object"){
322
            var getUrlVarName = {
323
                colNo: "col", colOrd: "ord", filter: "filter",
324
                filterBy: "filter-by", pageNo: "pg", exportType: "export",
325
                tableId: "table-id"
326
            };
327
            var flagFirst = location.search.length < 1 ? true : false;
328
            for(var r in rq){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
329
                var clue = flagFirst === true ? "?" : "&";
330
                url += clue + getUrlVarName[r] + "=" + rq[r];
331
                flagFirst = false;
332
            }
333
        }
334
        return url;
335
    }
336
};
337
338
//https://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript
339
var TableSingleton = (function(){
340
    // Instance stores a reference to the Singleton
341
    var instance;
342
    function initInstance(){
343
        // Singleton
344
        // Private methods and variables
345
        var BuildRequest = TableHelper.BuildRequest.Run;
346
        var Init = TableHelper.Init.Run;
347
        function Export(lnk, eType){
348
            return TableHelper.Export(lnk, eType, this.strDesc);   
349
        }
350
        function Filter(field){
351
            TableHelper.Filter.Run(field, instance, this.rq, this.strDesc);
352
        }
353
        function GoPage(lnk){
354
            TableHelper.GoPage.Run(lnk, instance, this.strDesc);
355
        }
356
        var LoadData = TableHelper.LoadData.Run;
357
        function ReloadData(tableId){
358
            var request = {};
359
            BuildRequest(request, tableId, this.strDesc);
360
            LoadData(tableId, request, instance);
361
        }
362
        function Sort(colNo, lnk){
363
            TableHelper.Sort(colNo, lnk, instance, this.strDesc, this.strAsc);
364
        }
365
366
        return {
367
            rq: null,
368
            strAsc: String.fromCharCode(9650), //&#9650;
369
            strDesc: String.fromCharCode(9660),//&#9660;
370
            
371
            ColumnHover: TableHelper.ColumnHover, //function(tableContainer, index)
372
            Export: Export,
373
            Filter: Filter,
374
            GoPage: GoPage,
375
            init: Init,
376
            LoadEndCalback: function(){},/*Allows override: function(tableId){if(tableId){...}}*/
377
            ReloadData: ReloadData,
378
            Sort: Sort
379
        };
380
    }
381
    return {
382
        //Get the Singleton instance if one exists, or create one if it doesn't
383
        getInstance: function(){
384
            if(!instance){
385
                instance = initInstance();
386
            }
387
            return instance;
388
        }
389
    };
390
})();
391
var table = TableSingleton.getInstance();
392